import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Map;
	
import javax.swing.*;
	
import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.plugin.NonPluginClass;
import com.speljohan.rsbot.script.*;
import com.speljohan.rsbot.script.wrappers.*;
	
import java.io.*;
import java.net.Socket;
	
	
public class RevivedCaviak extends Script implements ActionListener, ServerMessageListener, MouseListener {
	boolean startScript;
	
	//Options
	boolean useGUI;
	boolean useBot;
	boolean usePray;
	boolean optionGUI;
	
	//Irc vars
	String botNick;
	String botServer;
	String botOwner;
	String botPass;
	int botPort;
	
	//Constants 
	final static int TOKKUL_ID = 6529;
	final static int CAVE_EXIT_ID = 9357;
	final static int[] MONSTER_IDS = new int[] {2739, 2735, 2736, 2738, 2737, 2741, 2740, 2734};
	final static int[] LVL_90_IDS = new int[] {22740, 2739};
	int[] WAVE_HP = new int[] {10, 30, 70, 120, 180, 260, 300, 350,
			410, 490, 580, 680, 800, 880, 960, 1050, 1150, 1270, 1400,
			1540, 1700, 1820, 1950, 2090, 2250, 2420, 2600, 2800, 2960,
			3120, 3280, 3450, 3630, 3830, 4040, 4260, 4500, 4700, 4910,
			5130, 5370, 5620, 5880, 6160, 6400, 6640, 6890, 7150, 7430,
			7720, 8020, 8340, 8620, 8910, 9210, 9530, 9860, 10200, 10560,
			10880, 11200, 11520, 11770};
	final static RSTile[] ENTER_LOC = new RSTile[] {
		new RSTile(2437, 5167), new RSTile(2437, 5166),
		new RSTile(2438, 5167), new RSTile(2438, 5166),
		new RSTile(2439, 5167), new RSTile(2439, 5166)
	};
	
	//Info vars and other needed vars
	int[] expOnStart;
	int toksOnStart;
	int hpExpStartGame;
	int waits;
	int gamesPlayed;
	int attStyle;
	long startTime;
	long startUpdateTime;
	RSTile middleTile;
	ArrayList<JLabel> skillLabels;
	ArrayList<JLabel> infoLabels;

	int skillIndex;

	
	//For all info about the script.
	public RevivedCaviak() {
		setParameter("author", "Alowaniak");
		setParameter("version", 1.0);
		setParameter("name", "RevivedCaviak");
		setParameter("category", "Combat");
		setParameter("description", 
				"<head></head>\n" +
				"<body>\n" +
					"<center>" +
						"<h2>" + getName() + "</h2>" +
					"</center>\n" +
					"<p\n" +
					"<b>Author:</b> " + getAuthor() + "<p>\n" +
					"<b>Version:</b> " + getVersion() + "<p>\n" +
					"<center>" +
						"Hi der" +
					"</center>\n" +
				"</body>\n" +
				"</html>");
	}
	
	//The frame on start.
	public JFrame startFrame() {
		JFrame frame = new JFrame("RevivedCaviak - Options Selection.");
		frame.setLayout(new GridBagLayout());
		
		GridBagConstraints c = new GridBagConstraints();
		c.anchor = GridBagConstraints.ABOVE_BASELINE_LEADING;
		c.fill = GridBagConstraints.BOTH;
		
		//For the options panel.
		JPanel panel = new JPanel(new GridBagLayout());
		panel.setBorder(BorderFactory.createTitledBorder(
				BorderFactory.createLineBorder(Color.BLACK), "Game options"));
		c.gridx = 0;
		c.gridy = 0;
		JCheckBox checkBox = new JCheckBox("Make GUI");
		checkBox.setSelected(true);
		panel.add(checkBox, c);
		
		c.gridy = 1;
		checkBox = new JCheckBox("Make Bot");
		checkBox.setSelected(true);
		panel.add(checkBox, c);
		
		c.gridy = 2;
		checkBox = new JCheckBox("Use prayer");
		checkBox.setSelected(true);
		panel.add(checkBox, c);
		
		c.gridy = 3;
		ButtonGroup group = new ButtonGroup();
		JRadioButton radioButton = new JRadioButton("Gui option 1");
		radioButton.setToolTipText("<html> <img src=\"http://img115.imageshack.us/img115/5788/guiopt1xy6.jpg\">");
		group.add(radioButton);
		radioButton.setSelected(true);
		panel.add(radioButton, c);
		radioButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				optionGUI = ((JRadioButton)e.getSource()).isSelected();
			}			
		});
		
		c.gridy = 4;
		radioButton = new JRadioButton("GUI option 2");
		radioButton.setToolTipText("<html> <img src=\"\">");
		group.add(radioButton);
		panel.add(radioButton, c);
		radioButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				optionGUI = ((JRadioButton)e.getSource()).isSelected();
			}			
		});
		
		
		//END For the options panel.
		
		c.gridx = 0;
		c.gridy = 0;
		c.gridheight = 2;
		frame.add(panel, c);
		
		//For the IRC Bot panel.
		panel = new JPanel(new GridBagLayout());
		panel.setBorder(BorderFactory.createTitledBorder(
				BorderFactory.createLineBorder(Color.BLACK), "IRC Bot options"));
		c.gridx = 0;
		c.gridy = 0;
		c.gridheight = 1;
		JLabel label = new JLabel("Nickname:");
		panel.add(label, c);
		
		c.gridx = 1;
		c.gridwidth = 2;
		JTextField textField = new JTextField("nickname");
		panel.add(textField, c);
		
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		label = new JLabel("Server:");
		panel.add(label, c);
		
		c.gridx = 1;
		c.gridwidth = 2;
		textField = new JTextField("irc.moparisthebest.com");
		panel.add(textField, c);
		
		c.gridx = 0;
		c.gridy = 2;
		c.gridwidth = 1;
		label = new JLabel("Port:");
		panel.add(label, c);
		
		c.gridx = 1;
		c.gridwidth = 2;
		textField = new JTextField("6667");
		panel.add(textField, c);
		
		c.gridx = 0;
		c.gridy = 3;
		c.gridwidth = 1;
		label = new JLabel("Owner:");
		panel.add(label, c);
		
		c.gridx = 1;
		c.gridwidth = 2;
		textField = new JTextField("ircNickname");
		panel.add(textField, c);
		
		c.gridx = 0;
		c.gridy = 4;
		c.gridwidth = 1;
		label = new JLabel("Pass:");
		panel.add(label, c);
		
		c.gridx = 1;
		c.gridwidth = 2;
		textField = new JTextField("pass");
		panel.add(textField, c);
		//END For the IRC Bot panel.
		
		c.gridx = 1;
		c.gridy = 0;
		frame.add(panel, c);
		
		c.gridx = 1;
		c.gridy = 1;
		JButton button = new JButton("Start Script");
		button.setToolTipText("<html>Start Script!");
		frame.add(button, c);
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JButton button = ((JButton) e.getSource());
				JPanel frame = ((JPanel) button.getParent());
				JPanel panel = ((JPanel) frame.getComponent(0));
				useGUI = ((JCheckBox) panel.getComponent(0)).isSelected();
				useBot = ((JCheckBox) panel.getComponent(1)).isSelected();
				usePray = ((JCheckBox) panel.getComponent(2)).isSelected();
				
				panel = ((JPanel) frame.getComponent(1));
				botNick = ((JTextField) panel.getComponent(1)).getText();
				botServer = ((JTextField) panel.getComponent(3)).getText();
				botPort = Integer.parseInt(((JTextField) panel.getComponent(5)).getText());
				botOwner = ((JTextField) panel.getComponent(7)).getText();
				botPass = ((JTextField) panel.getComponent(9)).getText();
				startScript = true;
				JFrame framez = ((JFrame) ((JRootPane) ((JLayeredPane) frame.getParent()).getParent()).getParent());
				//When adding something to the frame it is added to the content pane, which is added to the layered pane,
				//which is added to the root pane, which is finally added to the frame.
				//So that's why so many casts are needed.
				framez.setVisible(false);
				framez = null;
			}
		});
		
		frame.pack();
		return frame;
	}
	
	//The main GUI.
	public JFrame createGUI(boolean option) {
		JFrame frame = new JFrame("RevivedCaviak GUI");
		frame.setLayout(new GridBagLayout());
		
		GridBagConstraints c = new GridBagConstraints();
		c.anchor = GridBagConstraints.ABOVE_BASELINE_LEADING;
		c.fill = GridBagConstraints.BOTH;
		c.insets = new Insets(0, 0, 3, 3);

		JPanel panel = new JPanel(new GridBagLayout());
		if(!optionGUI) {
			//For the info panel.
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Information", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
	
			c.gridx = 0;
			c.gridy = 0;
			JLabel label = new JLabel("Runtime");
			panel.add(label, c);
			
			c.gridx = 1;
			label = new JLabel("Games played");
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 1;
			label = new JLabel("Tokkuls collected");
			panel.add(label, c);
			
			c.gridx = 1;
			label = new JLabel("Tokkuls per game");
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 2;
			label = new JLabel("Wave you are in now");
			panel.add(label, c);
			
			c.gridx = 1;
			label = new JLabel("Average wave you die in");
			panel.add(label, c);
			//END For the info panel.
			
			c.gridx = 0;
			c.gridy = 0;
			frame.add(panel, c);
			
			//For the Skills panel.
			panel = new JPanel(new GridBagLayout());
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Skills", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
			label = new JLabel("Attack");
			panel.add(label, c);
			
			c.gridx = 1;
			label = new JLabel("Defence");
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 1;
			label = new JLabel("Strength");
			panel.add(label, c);
			
			c.gridx = 1;
			label = new JLabel("Hitpoints");
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 2;
			label = new JLabel("Ranged");
			panel.add(label, c);
			//END For the Skills panel.
			
			c.gridx = 1;
			c.gridy = 0;
			frame.add(panel, c);
			
			//For the actions panel.
			panel = new JPanel(new GridBagLayout());
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Actions", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
			
			c.gridx = 0;
			c.gridy = 0;
			JButton button = new JButton("Change attack style.");
			button.addActionListener(this);
			panel.add(button, c);
			
			//END For the actions panel.
			
			c.gridx = 0;
			c.gridy = 1;
			c.gridwidth = 2;
			frame.add(panel, c);
		} else {
			//For the info panel and buttons panel.
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Information", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
				
			c.gridx = 0;
			c.gridy = 0;
			JLabel label = new JLabel("Script running for: ");	//Info label 0
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 1;
			c.gridy = 0;
			label = new JLabel("Tokkuls in inven: ");			//Info label 1
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 1;
			label = new JLabel("Games played: ");				//Info label 2
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 1;
			c.gridy = 1;
			label = new JLabel("Average tokkuls per game: ");	//Info label 3
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 2;
			label = new JLabel("Wave you are in right now: "); //Info label 4
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 1;
			c.gridy = 2;
			label = new JLabel("Average wave you die in: "); 	//Info label 6
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 3;
			JButton button = new JButton("Change attack style.");
			button.addActionListener(this);
			panel.add(button, c);
			//END For the info and button panel.
			c.gridx = 0;
			c.gridy = 0;
			frame.add(panel, c);
			
			
			//For the skills panel
			panel = new JPanel(new GridBagLayout());
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Information", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
	
			c.gridx = 0;
			c.gridy = 0;
			label = new JLabel("Skill Name");
			label.setForeground(Color.RED);
			label.setBorder(BorderFactory.createMatteBorder(
	                2, 2, 0, 1, Color.BLACK));
			panel.add(label, c);
			
			c.gridx = 1;
			c.gridy = 0;
			label = new JLabel("Skill Exp");
			label.setForeground(Color.RED);
			label.setBorder(BorderFactory.createMatteBorder(
	                2, 1, 0, 1, Color.BLACK));
			panel.add(label, c);
			
			c.gridx = 2;
			c.gridy = 0;
			label = new JLabel("Trained");
			label.setForeground(Color.RED);
			label.setBorder(BorderFactory.createMatteBorder(
	                2, 1, 0, 1, Color.BLACK));
			panel.add(label, c);
			
			c.gridx = 3;
			c.gridy = 0;
			label = new JLabel("Skill Lvl");
			label.setForeground(Color.RED);
			label.setBorder(BorderFactory.createMatteBorder(
	                2, 1, 0, 1, Color.BLACK));
			panel.add(label, c);
			
			c.gridx = 4;
			c.gridy = 0;
			label = new JLabel("Trained");
			label.setForeground(Color.RED);
			label.setBorder(BorderFactory.createMatteBorder(
	                2, 1, 0, 1, Color.BLACK));
			panel.add(label, c);		
			
			
			for(int i = 0; i < 5; i++) {	//Loop trough skill names.
				c.gridx = 0;
				c.gridy = i+1;
				label = new JLabel(Skills.statsArray[i]);
				skillLabels.add(label);			//Labels 0-4
				label.addMouseListener(this);
				label.setBorder(BorderFactory.createMatteBorder(
		                0, 1, ic(i), 1, Color.BLACK));
				panel.add(label, c);
			}
			
			for(int i = 0; i < 5; i++) {	//Loop trough skill exp.
				c.gridx = 1;
				c.gridy = i+1;
				label = new JLabel("" + skills.getCurrentSkillExp(i));
				skillLabels.add(label);			//Labels 5-9
				label.addMouseListener(this);
				label.setBorder(BorderFactory.createMatteBorder(
		                0, 1, ic(i), 1, Color.BLACK));
				panel.add(label, c);
			}
			
			for(int i = 0; i< 5; i++) {	//Loop trough exp trained.
				c.gridx = 2;
				c.gridy = i+1;
				label = new JLabel("");
				skillLabels.add(label);			//Labels 10-14
				label.addMouseListener(this);
				label.setBorder(BorderFactory.createMatteBorder(
		                0, 1, ic(i), 1, Color.BLACK));
				panel.add(label, c);
			}
			
			for(int i = 0; i< 5; i++) {	//Loop trough skill level.
				c.gridx = 3;
				c.gridy = i+1;
				label = new JLabel("" + skills.getLvlByExp(skills.getCurrentSkillExp(i)));
				skillLabels.add(label);			//Labels 15-19
				label.addMouseListener(this);
				label.setBorder(BorderFactory.createMatteBorder(
		                0, 1, ic(i), 1, Color.BLACK));
				panel.add(label, c);
			}
			
			for(int i = 0; i< 5; i++) {	//Loop trough lvls trained.
				c.gridx = 4;
				c.gridy = i+1;
				label = new JLabel("");
				skillLabels.add(label);			//Labels 20-24
				label.addMouseListener(this);
				label.setBorder(BorderFactory.createMatteBorder(
		                0, 1, ic(i), 2, Color.BLACK));
				panel.add(label, c);
			}
			//END For the skills panel.
			c.gridx = 0;
			c.gridy = 1;
			frame.add(panel, c);
			
			//For the skill info panel.
			panel = new JPanel(new GridBagLayout());
			panel.setBorder(BorderFactory.createTitledBorder(
					BorderFactory.createCompoundBorder(
							BorderFactory.createEtchedBorder(
									new Color(204, 0, 0),new Color(153, 0, 0)),
							BorderFactory.createBevelBorder(0, 
									new Color(255, 0, 0), new Color(153, 0, 0), 
									new Color(153, 0, 0), new Color(102, 0, 0))),
					"Information", 0, 0, new Font("Tahoma", Font.ITALIC, 12), new Color(255, 0, 0)));
	
			c.gridx = 0;
			c.gridy = 0;
			label = new JLabel("Exp till next level:");	//Info label 6
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 1;
			label = new JLabel("Percent to next level:");		//Info label 7
			infoLabels.add(label);
			panel.add(label, c);
			
			c.gridx = 0;
			c.gridy = 2;
			label = new JLabel("Exp per minute:");				//Info label 8
			infoLabels.add(label);
			panel.add(label, c);
			//END For the skill info panel.
			
			c.gridx = 0;
			c.gridy = 2;
			frame.add(panel, c);
		}
		
		frame.pack();
		frame.setSize(new Dimension(frame.getWidth() + 50, + frame.getHeight() + 50));
		return frame;
	}
	
	//What happens on start.
	public boolean onStart(Map<String, String> args) {
		ToolTipManager.sharedInstance().setInitialDelay(0);
		if(!(new File("Prog's and Log's FightCaviak").exists()))
			new File("Prog's and Log's FightCaviak").mkdir();
		toksOnStart = 0;
		startScript = false;
		useGUI = false;
		useBot = false;
		usePray = false;
		gamesPlayed = 0;
		attStyle = -1;
		expOnStart = new int[5];
		startTime = System.currentTimeMillis();
		skillLabels = new ArrayList<JLabel>();
		infoLabels = new ArrayList<JLabel>();
		Bot.getEventManager().addListener(this);
		
		startFrame().setVisible(true);
		int i = 0;
		while(!startScript) {
			i++;
			if(i > 1800) {
				JOptionPane.showMessageDialog(null, "Timed out, 3 minutes passed since you clicked start.");
				return false;
			}
			wait(100);
		}
		
		try {
			if(useBot) {
				FircBot bot = new FircBot(botNick, botServer, botPort, botOwner, botPass, this);
				bot.start();
			}
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "I'm sorry something got " +
					"messed up with creating the irc bot\n" +
					"Maybe you entered something wrong, stopping script now.");
			e.printStackTrace();
		}
		
		if(useGUI) {
			JFrame frame = createGUI(optionGUI);
			frame.setVisible(true);
			GuiUpdater updater = new GuiUpdater(frame, this);
			updater.start();
		}
		
		return true;
	}
	
	//The main loop.
	@Override
	public int loop() {
		
		for(int i = 0; i < 5; i++) {
			if(expOnStart[i] < 1)
				expOnStart[i] = skills.getCurrentSkillExp(i);
		}
		
		if(attStyle >= 0)
			if(changeAttStyle(attStyle))
				attStyle = -1;
		
		if(getEnergy() > random(50, 90))
			setRun(true);
		
		if(toksOnStart < 1)
			toksOnStart = getInventoryCount(TOKKUL_ID);
		
		
			int ran = random(0, ENTER_LOC.length-1);
		RSObject caveEnter = getObjectAt(ENTER_LOC[ran]);
		if(caveEnter != null) {
			hpExpStartGame = skills.getCurrentSkillExp(STAT_HITPOINTS);
			if(getMyPlayer().isMoving())
				return random(500, 1000);
			
			if(getMyPlayer().getInteracting() != null) {
				runAway();
				return random(500, 1500);
			}
			try {
				if(!(tileOnScreen(ENTER_LOC[ran]))) {
					goTo(ENTER_LOC[ran], 1);
					turnToTile(ENTER_LOC[ran]);
				}
			} catch (Exception e) {
				log("FFs domme nullpointer bug weer");
			}
			
			atTile(ENTER_LOC[ran], "Enter");
			
			return random(500, 1000);
		}
		
		RSObject caveExit = findObject(CAVE_EXIT_ID);
		if(caveExit != null) {
			int midX = caveExit.getLocation().getX() - random(12, 17);
			int midY = caveExit.getLocation().getY() - random(28, 38);
			middleTile = new RSTile(midX, (midY));		
		}
		
		
		RSNPC attNPC = getNearestFreeNPCByID(MONSTER_IDS);
		
		if(attNPC == null)
			attNPC = getNearestNPCByID(MONSTER_IDS);
		
		if(getNearestNPCByID(3741) != null) {
			attNPC = getNearestNPCByID(3741);
			if(usePray && skills.getCurrentSkillLevel(STAT_PRAYER) > random(3, 10) &&
					skills.getRealSkillLevel(STAT_PRAYER) >= 43)
				turnPrayer(19, true);
		} else if(getNearestNPCByID(LVL_90_IDS) != null) {
			attNPC = getNearestNPCByID(LVL_90_IDS);
			if(usePray && skills.getCurrentSkillLevel(STAT_PRAYER) > random(3, 10) &&
					skills.getRealSkillLevel(STAT_PRAYER) >= 41)
				turnPrayer(18, true);
		} else {
			turnPrayer(19, false);
			turnPrayer(18, false);
		}
		
		if(attNPC != null) {
			if(getMyPlayer().getInteracting() != null) {
				waits = 0;
				return random(500, 1000);
			}
			
			if(tileOnScreen(attNPC.getLocation()) && !attNPC.isInCombat()) {
				atNPC(attNPC, "attack");
				waits = 0;
			} else if(distanceTo(attNPC.getLocation()) > 7 && !attNPC.isInCombat()){
				walkHalfMM(attNPC);
				waits = 0;
			}
			return random(500, 1500);
		}
		
		waits++;
		try {
			if(waits > 3 && !getMyPlayer().isMoving() && middleTile != null)
				goTo(middleTile, 2);
			if(waits > 6 && distanceTo(middleTile) > 50) {
				log("Sorry, got lost. Stopping script.");
				stopAllScripts();
			}
		} catch (Exception e) {
			log("Wtf again the weird nullpointer exception");
		}
		return random(800, 1000);
	}
	
	//Small method to go to npc.	
	public void walkHalfMM(RSNPC c) {
		RSTile t = c.getLocation();
		walkTileMM(new RSTile((int) ((t.getX() + getMyPlayer().getLocation().getX())/2.5),
				(int) ((t.getY() + getMyPlayer().getLocation().getY())/2.5)));
	}
	
	//Method to "travel".
	public boolean goTo(RSTile t,int range) {   //New walking method by Bug5532.
		if (distanceTo(t) < range) return true;
	
		if (distanceTo(t) < 13){
			walkTileMM(t);
			wait(random(500,1000));
			return false;
		}
		
		while(true){
			t = new RSTile( ((t.getX()+getMyPlayer().getLocation().getX())/2)+random(-1,1),
					((t.getY()+getMyPlayer().getLocation().getY())/2)+random(-1,1) ) ;
			if (distanceTo(t) < 15){
				walkTileMM(t);
				wait(random(500,1000));
				break;
			}
		}
		return false;
	}
	
	//Method to run away.
	public int runAway() {
		RSTile foo, bar;
		foo = getMyPlayer().getLocation();
		setRun(true);
		
		bar = new RSTile(foo.getX() + random(8, 10), foo.getY() + random(8, 10));
		
		walkTileMM(bar);
		while (getMyPlayer().isMoving()) {
			wait(random(2000, 4000));
		}
		wait(random(1000, 2000));
		walkTileMM(foo);
		return 1000;
	}
	
	//Method to turn prayer on.
	public boolean turnPrayer(int prayID, boolean activate) {
		int prayInterID = 271;
		int praySetting = prayID+83;
		
		
		if(prayID > 4)
			praySetting -= 2;
			
		if(prayID > 12)
			praySetting -= 2;
			
		if(prayID > 16)
			praySetting -= 1;
			
		if(prayID > 23)
			praySetting -= 2;
			
		if(prayID == 3 || prayID == 4 || prayID == 11 || prayID == 12 || prayID == 21 || prayID == 22)
			praySetting = prayID + 859;
			
			
		
		if(prayID == 16)
			prayID = 24;
		else if(prayID > 16)
			prayID -= 1;
		if(prayID > 24)
			prayID += 1;
		if(intToBool(getSetting(praySetting)) == activate)
			return true;
		openTab(TAB_PRAYER);
		wait(random(300, 500));
		if(activate)
			return atInterface(prayInterID, ((prayID*2)+5), "Activate");
		else
			return atInterface(prayInterID, ((prayID*2)+5), "Activate");
	}
	
	public boolean intToBool(int i) {
		return i!=0;
	}
	
	public int ic(int i) {
		if(i<4)
			return 0;
		return 2;
	}
	
	public int getSkillIndex(MouseEvent e) {
		for(int i = 0; i < skillLabels.size(); i++) {
			if(skillLabels.get(i).equals(e.getComponent())) {
				if(i<5)
					return i;
				if(i<10)
					return i-5;
				if(i<15)
					return i-10;
				if(i<20)
					return i-15;
				return i-20;
			}
		}
		return -1;
	}
	
	public long runtime() {
		return System.currentTimeMillis() - startTime;
	}
	
	//Method for the tooltip text (might going to use it if I add another GUI lookout too)
	public String getToolTipText(int index) {		
		String str = "<html>";
		str += Skills.statsArray[index];
		str += "<br>";
		str += "Exp: " + curExp(index);
		str += "<br>";
		str += "Trained: " + trainedExp(index);
		str += "<br>";
		str += "Lvl: " + curLvl(index);
		str += "<br>";
		str += "Trained: " + trainedLvl(index);
		str += "<br>";
		str += "Exp/hour: " + ((double)((double)expPSec(index)*60*60)/1000) + "K";
		str += "<br>";
		str += "Percent to next lvl: " + percNextLvl(index) + "%";
		str += "<br>";
		str += "Exp till next lvl: " + expNextLvl(index);
		str += "<br>";
		str += "Est. time till next level: " + timeNextLvl(index);
		
		return str;
	}
	
	//Methods for calculating exp things etc.
	public int curExp(int index) {
		return skills.getCurrentSkillExp(index);
	}
	
	public int trainedExp(int index) {
		return (skills.getCurrentSkillExp(index) - expOnStart[index]);
	}
	
	public int curLvl(int index) {
		return skills.getRealSkillLevel(index);
	}
	
	public int trainedLvl(int index) {
		return (skills.getRealSkillLevel(index) - 
				skills.getLvlByExp(expOnStart[index]));
	}
	
	public long expPSec(int index) {
		long millis = runtime();
		long secs = millis/1000;
		
		int exp = trainedExp(index);
		long expPMilli = 0;
		try {
			expPMilli = ((long) exp/secs);
		} catch (Exception e) {
			expPMilli = 0;
		}
		return expPMilli;
	}
	
	public int percNextLvl(int index) {
		return skills.getPercentToNextLevel(index);
	}
	
	public int expNextLvl(int index) {
		return skills.getXPToNextLevel(index);
	}
	
	public String timeNextLvl(int index) {
		try {
			int expNeeded = expNextLvl(index);
			long expPerMillis = ((long) expNeeded/expPSec(index));
			long hours = expPerMillis/60/60;
			expPerMillis -= hours*60*60;
			long minutes = expPerMillis/60;
			expPerMillis -= minutes*60;
			long seconds = expPerMillis;
			
			return hours + ":" + minutes + ":" + seconds;
		} catch (Exception e) {
			return "0:0:0";
		}
	}
	
	public int whatWave(int exp) {
		for(int i = WAVE_HP.length-1; i >= 0 ; i--)
			if(exp/(4.0/3.0) >= WAVE_HP[i])
				return i+1;		
		return 1;
	}

	//Events
	@Override
	public void serverMessageRecieved(ServerMessageEvent e) {
		String mes = e.getMessage();
		if(mes.contains("have been defeated"))
			gamesPlayed++;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand().contains("attack style")) {
			try {
				String[] styles = new String[] {"0", "1", "2", "3"}; 
				int attStyle = Integer.parseInt((String) JOptionPane.showInputDialog(null, "Choose attack style; 0 = top left, 1 = top right,\n2 = bottom left, 3 = bottom right(NOT ALWAYS THERE!).",
							"Choose attack style", JOptionPane.QUESTION_MESSAGE, null,
							styles, styles[0]));
				this.attStyle = attStyle;
			} catch (Exception exc) {
			}
		}
	}
	
	public boolean changeAttStyle(int style) {
		if(getFightMode() == style)
			return true;
		setFightMode(style);
		wait(random(700, 1400));
		return getFightMode() == style;
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		JFrame frame = ((JFrame) ((JRootPane) ((JLayeredPane) ((JPanel) ((JPanel) ((JLabel) e.getSource()).getParent()).getParent()).getParent()).getParent()).getParent());

		int index = getSkillIndex(e);
		if(index >= 0) {
			skillIndex=index;
			infoLabels.get(6).setForeground(Color.BLUE);
			infoLabels.get(6).setText("Exp till next "
									+ Skills.statsArray[skillIndex] + " lvl: "								
									+ (double)skills.getXPToNextLevel(skillIndex)/1000 + "K");
			infoLabels.get(7).setForeground(Color.BLUE);
			infoLabels.get(7).setText("Percent to next " 
									+ Skills.statsArray[skillIndex] + " lvl: " 
									+ skills.getPercentToNextLevel(skillIndex) + "%");
		}
		frame.validate();
		frame.repaint();
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		JFrame frame = ((JFrame) ((JRootPane) ((JLayeredPane) ((JPanel) ((JPanel) ((JLabel) e.getSource()).getParent()).getParent()).getParent()).getParent()).getParent());
		infoLabels.get(6).setForeground(Color.BLACK);
		infoLabels.get(7).setForeground(Color.BLACK);
		frame.validate();
		frame.repaint();
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
}


//For updating the GUI.
class GuiUpdater extends Thread implements NonPluginClass {
	JFrame frame;
	RevivedCaviak script;
	
	public GuiUpdater(JFrame frame, RevivedCaviak script) {
		this.frame = frame;
		this.script = script;
	}
	
	public void run() {
		while(true) {
			if(!script.optionGUI) {			
				long millis = script.runtime();
				long hours = millis/1000/60/60;
				millis -= hours*1000*60*60;
				long minutes = millis/1000/60;
				millis -= minutes*1000*60;
				long seconds = millis/1000;
				
				JPanel panel = ((JPanel) ((JPanel) frame.getContentPane()).getComponent(0));
				JLabel label = ((JLabel) panel.getComponent(0));
				label.setText("Runtime: " + hours + ":" + minutes + ":" + seconds);
				
				label = ((JLabel) panel.getComponent(1));
				label.setText("Games played: " + script.gamesPlayed);
				
				label = ((JLabel) panel.getComponent(2));
				label.setText("Tokkuls collected: " + 
						(script.getInventoryCount(RevivedCaviak.TOKKUL_ID) - script.toksOnStart));
				
				
				label = ((JLabel) panel.getComponent(3));
				if((script.getInventoryCount(RevivedCaviak.TOKKUL_ID)-script.toksOnStart)>0 &&
						script.gamesPlayed > 0)
					label.setText("Tokkuls/game: " + ((script.getInventoryCount(RevivedCaviak.TOKKUL_ID) -
							script.toksOnStart))/script.gamesPlayed);
				else
					label.setText("Average tokkuls per game: 0");
				
				label = ((JLabel) panel.getComponent(4));
				if(script.getSetting(334)!=0)
					label.setText("Wave you are in now: " + 
							script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
									script.hpExpStartGame));
				else
					label.setText("Wave you are in now: 0");
				
				label = ((JLabel) panel.getComponent(5));
				if(script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
						script.expOnStart[RevivedCaviak.STAT_HITPOINTS]) > 0 && script.gamesPlayed > 0)
					label.setText("Average wave you die in: " + 
							script.whatWave((script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
									script.expOnStart[RevivedCaviak.STAT_HITPOINTS])/script.gamesPlayed));
				else
					label.setText("Average wave you die in: None yet");
				//Makes the label average wave you die in, messy because of long names etc.
				
				panel = ((JPanel) ((JPanel) frame.getContentPane()).getComponent(1));
				
				for(int i = 0; i < 5; i++)
					((JLabel) panel.getComponent(i)).setToolTipText(script.getToolTipText(i));
				
			} else {
				//Update first info panel.
				long millis = script.runtime();
				long hours = millis/1000/60/60;
				millis -= hours * 1000 * 60 * 60;
				long minutes = millis/1000/60;
				millis -= minutes * 1000 * 60;
				long seconds = millis/1000;
				script.infoLabels.get(0).setText("Running time: " + hours + ":" + minutes + ":" + seconds + ".");
				script.infoLabels.get(2).setText("Games played: " + script.gamesPlayed);
				script.infoLabels.get(1).setText("Tokkuls collected: " + (script.getInventoryCount(RevivedCaviak.TOKKUL_ID)-script.toksOnStart));
				if(script.getInventoryCount(RevivedCaviak.TOKKUL_ID)-script.toksOnStart>0 && script.gamesPlayed > 0)
					script.infoLabels.get(3).setText("Average tokkuls per game: " + ((script.getInventoryCount(RevivedCaviak.TOKKUL_ID)-script.toksOnStart)/script.gamesPlayed));
				else
					script.infoLabels.get(3).setText("Average tokkuls per game: 0");
				
				if(script.getSetting(334)!=0)
					script.infoLabels.get(4).setText("Wave you are in now: " + script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - script.hpExpStartGame));
				else
					script.infoLabels.get(4).setText("Wave you are in now: 0");
				
				if(script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - script.expOnStart[RevivedCaviak.STAT_HITPOINTS]) > 0 && script.gamesPlayed >0)
					script.infoLabels.get(5).setText("Average wave you die in: " + script.whatWave((script.curExp(RevivedCaviak.STAT_HITPOINTS) - script.expOnStart[RevivedCaviak.STAT_HITPOINTS])/script.gamesPlayed));
				else
					script.infoLabels.get(5).setText("Average wave you die in: None yet");
				//End first info panel.
				
				//Update skills panel.
				for(int i = 0; i<24; i++) {
					if(i<5) 
						updateExp(i);
					else if(i<10)
						updateTrainedExp(i-5);
					else if(i<15)
						updateLvls(i-10);
					else if(i<20)
						updateLvlsTrained(i-15);
				}
				//End skills panel.
				
				//Update skills info panel.
				minutes += (hours * 60);
				if(script.skillIndex>=0) {
					int skillExpTrained = script.curExp(script.skillIndex) - script.expOnStart[script.skillIndex];
					if(skillExpTrained > 0 && minutes > 0)
						script.infoLabels.get(8).setText(Skills.statsArray[script.skillIndex] + " Exp per minute: " + (skillExpTrained/minutes));
					else
						script.infoLabels.get(8).setText(Skills.statsArray[script.skillIndex] + " Exp per minute: 0");
				}
				//End skills info panel.
				
			}

			frame.validate();
			frame.repaint();
			try {
				Thread.sleep(100);
			} catch (Exception e) {}
			if(!frame.isValid() && !frame.isVisible() && !script.isActive)
				break;
		}
	}
	
	public void updateExp(int index) {			//Updates the exp labels
		if(!script.skillLabels.get(index+5).getText().equals("" + script.curExp(index))) {
			script.startUpdateTime = System.currentTimeMillis();
			script.skillLabels.get(index+5).setForeground(Color.BLUE);
			script.skillLabels.get(index+5).setText("" + script.curExp(index));
		} else {
			if(System.currentTimeMillis() - 2000 > script.startUpdateTime) {
				script.skillLabels.get(index+5).setForeground(Color.BLACK);
			}
		}
	}
	
	public void updateTrainedExp(int index) {	//Updates the trained exp labels
		if(!script.skillLabels.get(index+10).getText().equals("" + (script.curExp(index) - script.expOnStart[index]))) {
			script.skillLabels.get(index+10).setForeground(Color.BLUE);
			script.skillLabels.get(index+10).setText("" + (script.curExp(index) - script.expOnStart[index]));
		} else {
			if(System.currentTimeMillis() - 2000 > script.startUpdateTime) {
				script.skillLabels.get(index+10).setForeground(Color.BLACK);
			}
		}
	}
	
	public void updateLvls(int index) {			//Updates the level labels
		if(!script.skillLabels.get(index+15).getText().equals("" + script.curLvl(index))) {
			script.skillLabels.get(index+15).setForeground(Color.BLUE);
			script.skillLabels.get(index+15).setText("" + script.curLvl(index));
		} else {
			if(System.currentTimeMillis() - 10000 > script.startUpdateTime) {
				script.skillLabels.get(index+15).setForeground(Color.BLACK);
			}
		}
	}
	
	public void updateLvlsTrained(int index) {	//Updates the trained level labels
		if(!script.skillLabels.get(index+20).getText().equals("" + (script.curLvl(index) - script.skills.getLvlByExp(script.expOnStart[index])))) {
			script.skillLabels.get(index+20).setForeground(Color.BLUE);
			script.skillLabels.get(index+20).setText("" + (script.skills.getLvlByExp(script.curExp(index)) - script.skills.getLvlByExp(script.expOnStart[index])));
		} else {
			if(System.currentTimeMillis() - 10000 > script.startUpdateTime) {
				if((script.skills.getLvlByExp(script.curExp(index)) - script.skills.getLvlByExp(script.expOnStart[index])) > 0) {
					script.skillLabels.get(index+20).setForeground(Color.MAGENTA);
				} else {
					script.skillLabels.get(index+20).setForeground(Color.BLACK);
				}
			}
		}
	}
}
	
	
//For the IRC Bot.
//Used PircBot for example.
class FircBot extends Thread implements NonPluginClass{
	RevivedCaviak script;
	Frame frame;
	String username;
	String server;
	String owner;
	String pass;
	int port;
	boolean isConnected = false;
    BufferedReader bufReader;
    BufferedWriter bufWriter;

    //Creating the bot and connecting etc.
	public FircBot(String username, String server, int port, 
			String owner, String pass, RevivedCaviak script) {
		this.username = username;
		this.server = server;
		this.owner = owner;
		this.pass = pass;
		this.port = port;
		this.script = script;
		try {
			this.connect();
		} catch(Exception e) {
			isConnected = false;
		}
	}
	
	//Method to connect.
	private void connect() throws IOException {
		Socket socket =  new Socket(server, port);
		
		InputStreamReader inStreamR = new InputStreamReader(socket.getInputStream());
        OutputStreamWriter outStreamW= new OutputStreamWriter(socket.getOutputStream());

        bufReader = new BufferedReader(inStreamR);
        bufWriter = new BufferedWriter(outStreamW);
        
        sendLine("NICK " + this.username);
        sendLine("USER " + this.username + " 8 * :" + " FircBot");
        
        isConnected = true;
	}
	
	//Method to send a (raw) line.
	private void sendLine(String line) {
        try {
            bufWriter.write(line + "\r\n");
            bufWriter.flush();
        }
        catch (Exception e) {
            // Silent response - just lose the line.
        }
	}
	
	//Method to send a notice.
	private void sendNotice(String mes, String user) {
		sendLine("NOTICE " + user + " " + mes);
	}
	
	//The loop.
	public void run() {
		while(true) {		
			if(!script.isActive && script.runtime() > 3*60*1000) {
				sendNotice("Script stopped, stopping too.", owner);
				break;
			}
			try {
				String line;
				while((line = bufReader.readLine()) != null) {
					if(line.startsWith("PING ")) {
						this.sendLine("PONG " + line.substring(5));
						continue;
					}
					try {
						this.handleLine(line);
					} catch (Exception e) {
						
					}
				}
				Thread.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
				break;
			}
		}
		this.isConnected = false;
	}
		
	//To handle the lines (commands etc.).
	private void handleLine(String line) {
		String message = line.substring(line.lastIndexOf(':') + 1);
		String sender = line.substring(1, line.indexOf('!'));
		
		if(line.contains("owner") && line.contains(pass)) {
			this.owner = sender;
			sendNotice("New owner: " + owner, sender);
			return;
		}
		
		if(sender.equals(owner)) {
			if(message.startsWith(".do")) {
				this.sendLine(message.substring(4));
			}
			
			if(message.startsWith("setStyle")) {
				String[] temp = message.split(" ");
				try {
					script.attStyle = Integer.parseInt(temp[1]);
					sendNotice("Hopefully changed att style correctly", sender);
				} catch (Exception e) {
					sendNotice("Something went wrong changing att style, you probably didn't insert a valid number.", sender);
				}
			}
			
			if(message.startsWith("skills")) {
				String[] temp = message.split(" ");
				if(temp.length < 2) {
					sendNotice("Wrong usage should be: skills [index] (optional:)[lastIndex]", 
							sender);
				} else if (temp.length < 3) {
					try {
						int index = Integer.parseInt(temp[1]);
						String skillIn = script.getToolTipText(index);
						temp = skillIn.split("<br>");
						temp[0] = temp[0].substring(5);
						
						for(int i = 0; i < temp.length; i++) {
							sendNotice(temp[i], sender);
						}
					} catch (Exception e) {
						sendNotice("Something went wrong, you probably entered an invalid number", 
								sender);
					}
				} else {
					try{
						int index = Integer.parseInt(temp[1]);
						int lastIndex = Integer.parseInt(temp[2]);
						
						for(int i = index ; i <= lastIndex; i++) {
							String skillIn = script.getToolTipText(i);
							temp = skillIn.split("<br>");
							temp[0] = temp[0].substring(5);
							
							for(int j = 0; j < temp.length; j++) {
								sendNotice(temp[j], sender);
							}
							sendNotice("-----------------------", sender);
						}
					} catch (Exception e) {
						sendNotice("Something went wrong, you probably entered an invalid number", 
								sender);
					}
				}
			}
			
			if(message.startsWith("runtime?")) {
				long millis = script.runtime();
				long hours = millis/1000/60/60;
				millis -= hours*1000*60*60;
				long minutes = millis/1000/60;
				millis -= minutes*1000*60;
				long seconds = millis/1000;
				sendNotice(hours + ":" + minutes + ":" + seconds, sender);
			}
			if(message.startsWith("games")) {
				sendNotice("Games played: " + script.gamesPlayed, sender);
			}
			if(message.startsWith("toks")) {
				sendNotice("Collected: " +
						(script.getInventoryCount(RevivedCaviak.TOKKUL_ID) - script.toksOnStart), sender);
				if((script.getInventoryCount(RevivedCaviak.TOKKUL_ID)-script.toksOnStart)>0 &&
						script.gamesPlayed > 0)
					sendNotice("Tokkuls/game: " + ((script.getInventoryCount(RevivedCaviak.TOKKUL_ID) -
							script.toksOnStart))/script.gamesPlayed, sender);
				else
					sendNotice("Average tokkuls per game: 0", sender);
			}
			if(message.startsWith("wave")) {
				if(script.getSetting(334)!=0)
					sendNotice("Wave you are in now: " + 
							script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
									script.hpExpStartGame),
						sender);
				else
					sendNotice("Wave you are in now: 0", sender);
				
				if(script.whatWave(script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
						script.expOnStart[RevivedCaviak.STAT_HITPOINTS]) > 0 && script.gamesPlayed > 0)
					sendNotice("Average wave you die in: " + 
							script.whatWave((script.curExp(RevivedCaviak.STAT_HITPOINTS) - 
									script.expOnStart[RevivedCaviak.STAT_HITPOINTS])/script.gamesPlayed), 
									sender);
				else
					sendNotice("Average wave you die in: None yet", sender);
			}
		}
	}
}
